package com.dmjy.boot.common.util;

import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @author 敖癸
 * @formatter:on
 * @since 2023/7/31
 */
public class DateUtil  {

    private static final DateTimeFormatter DATE_TIME_FORMATTER;

    static {
        /* 2023/10/15 or 2023-10-15 */
        DateTimeFormatter isoLocalDate = new DateTimeFormatterBuilder()
                .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                .optionalStart().appendLiteral('/').optionalEnd()
                .optionalStart().appendLiteral('-').optionalEnd()
                .optionalStart().appendValue(ChronoField.MONTH_OF_YEAR, 2)
                .optionalStart().appendLiteral('/').optionalEnd()
                .optionalStart().appendLiteral('-').optionalEnd()
                .optionalStart().appendValue(ChronoField.DAY_OF_MONTH, 2)
                .toFormatter();

        /* 10/15/2023 */
        DateTimeFormatter noLocalDate = new DateTimeFormatterBuilder()
                .optionalStart().appendValue(ChronoField.MONTH_OF_YEAR, 2)
                .optionalStart().appendLiteral('/').optionalEnd()
                .optionalStart().appendLiteral('-').optionalEnd()
                .optionalStart().appendValue(ChronoField.DAY_OF_MONTH, 2)
                .optionalStart().appendLiteral('/').optionalEnd()
                .optionalStart().appendLiteral('-').optionalEnd()
                .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                .toFormatter();
        /* 支持的格式： HH, HH:mm, HH:mm:ss, HH:mm:ss.SSS, HH:mm:ss.Z*/
        DateTimeFormatter isoLocalTime = new DateTimeFormatterBuilder()
                .appendValue(ChronoField.HOUR_OF_DAY, 2)
                .optionalStart().appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2)
                .optionalStart().appendLiteral(':').appendValue(ChronoField.SECOND_OF_MINUTE, 2)
                .optionalStart().appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
                .optionalStart().appendZoneId()
                .toFormatter();

        DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
                .optionalStart().appendOptional(isoLocalDate).optionalEnd()
                .optionalStart().appendOptional(noLocalDate).optionalEnd()
                .optionalStart().appendLiteral(' ').optionalEnd()
                .optionalStart().appendLiteral('T').optionalEnd()
                .optionalStart().appendLiteral("'T'").optionalEnd()
                .optionalStart().appendOptional(isoLocalTime).optionalEnd()
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .toFormatter(Locale.CHINA);
    }

    /**
     * 时间字符串反序列化时间
     *
     * @param dateStr
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/9/25 - 10:02
     */
    public static Date parse(String dateStr) {
        return parse(dateStr, ZonedDateTime.now().getOffset());
    }

    /**
     * 指定偏移量后的序列化时间
     *
     * @param dateStr
     * @param offsetId +08 | -09 | +02:30
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/9/25 - 10:03
     */
    public static Date parse(String dateStr, String offsetId) {
        ZoneOffset offset = ZoneOffset.of(offsetId);
        return parse(dateStr, offset);
    }

    /**
     * 指定偏移量后的序列化时间
     *
     * @param dateStr
     * @param offset
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/9/25 - 10:03
     */
    public static Date parse(String dateStr, ZoneOffset offset) {
        String value = dateStr.trim();
        if (StringUtils.hasText(value)) {
            LocalDateTime localDateTime = LocalDateTime.parse(value, DATE_TIME_FORMATTER);
            return Date.from(localDateTime.toInstant(offset));
        }
        return null;
    }



    /**
     * 返回两个时间中时间早的那一个
     *
     * @param o1
     * @param o2
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/8/2 - 23:22
     */
    public static Date min(Date o1, Date o2) {
        if (o1.getTime() < o2.getTime()) {
            return o1;
        }
        return o2;
    }

    /**
     * 返回两个时间中时间晚的那一个
     *
     * @param o1
     * @param o2
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/8/2 - 23:22
     */
    public static Date max(Date o1, Date o2) {
        if (o1.getTime() > o2.getTime()) {
            return o1;
        }
        return o2;
    }

    /**
     * 获取指定小时的开始时间
     *
     * @param hour
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/8/1 - 0:00
     */
    public static Date beginOfHour(int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取指定小时的结束时间
     *
     * @param hour
     * @return java.util.Date
     * @author 敖癸
     * @since 2023/8/1 - 0:01
     */
    public static Date endOfHour(int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

}
